package my.jieh.tips.net;
import java.io.*;
import java.net.*;
import java.util.*;

public class EchoClientTest {

  BufferedReader reader;
  PrintWriter writer;
  int port;
  int timeout;
  Socket socket;
  SocketAddress socketAddress;
  String host;

  private static final int ECHO_PORT = 7;

  public EchoClientTest() {
    this("localhost", ECHO_PORT);
  }

  public EchoClientTest(String host) {
    this(host, ECHO_PORT);
  }

  public EchoClientTest(String host, int port) {
    this.host = host;
    this.port = port;
    if (getSocketNoTimeout()) {
      doWork();
    }
  }


  public EchoClientTest(
      String host, int port, int timeout) {
    this.host = host;
    this.port = port;
    this.timeout = timeout;
    if (getSocketConnectTimeout()) {
      doWork();
    }
  }

  public EchoClientTest(
      String host, int port, int timeout, boolean b) {
    this.host = host;
    this.port = port;
    this.timeout = timeout;
    if (getSocketSetTimeout()) {
      doWork();
    }
  }

  public boolean getSocketNoTimeout() {
    try {
      System.out.println("Not connected, waiting...");
      socket = new Socket(host, port);
      System.out.println("Connected. Enter 'quit' to end.");
    } catch (UnknownHostException e) {
      System.err.println("Don't know about host: " + host + ".");
      return false;
    } catch (IOException ioe) {
      System.err.println("Connect: " + ioe.getMessage());
      return false;
    }
    return true;
  }

  public boolean getSocketConnectTimeout() {
    try {
      System.out.println("Not connected, waiting...");
      socketAddress = new InetSocketAddress(host, port);
      socket = new Socket();
      socket.connect(socketAddress, timeout);
      System.out.println("Connected. Enter 'quit' to end.");
    } catch(UnknownHostException e) {
      System.err.println("Don't know about host: " + host + ".");
      return false;
    } catch(SocketTimeoutException ste) {
      System.err.println("Timeout: " + ste.getMessage());
      return false;
    } catch(IOException ioe) {
      System.err.println("Connect: " + ioe.getMessage());
      return false;
    }
    return true;
  }

  public boolean getSocketSetTimeout() {
    try {
      socketAddress = new InetSocketAddress(host, port);
      socket = new Socket();
      try {
        socket.setSoTimeout(timeout);
      } catch (SocketException se) {
        System.err.println("Could not set timeout: " +
          se.getMessage());
        return false;
      }
      System.out.println("Not connected, waiting...");
      socket.connect(socketAddress);
      System.out.println(
        "Connected. Enter 'quit' to end.");
    } catch (UnknownHostException e) {
      System.err.println("Don't know about host: " +
        host + ".");
      return false;
    } catch (SocketTimeoutException ste) {
      System.err.println("Timeout: " +
        ste.getMessage());
      return false;
    } catch (IOException ioe) {
      System.err.println("Connect: " +
        ioe.getMessage());
      return false;
    }
    return true;
  }

  public void doWork() {
    try {
      writer = new PrintWriter(
        socket.getOutputStream(), true);
      reader = new BufferedReader(
        new InputStreamReader(socket.getInputStream()));
    } catch (IOException e) {
      System.err.println(
        "Couldn't get I/O for the connection to: " +
        host + ".");
      return;
    }

    try {
      BufferedReader stdIn = new BufferedReader(
        new InputStreamReader(System.in));
      String userInput;

      while ((userInput = stdIn.readLine()) != null) {
        writer.println(userInput);
        System.out.println("echo: " +
          reader.readLine());
        if (userInput.equals("quit")) {
          return;
        }
      }

      writer.close();
      reader.close();
      stdIn.close();
      socket.close();
    } catch(IOException ioe) {
      System.err.println("IOException: " +
        ioe.getMessage());
      return;
    }
  }

  public static void main(String args[]) {
    int thePort = 0;
    int theTimeout = 0;

    if (args.length == 1 && args[0].equals("?")) {
      System.out.println(
        "No args: localhost, port 7,  no timeout.");
      System.out.println(
        "1 arg: arghost, port 7, no timeout.");
      System.out.println(
        "2 args: argHost, argPort, no timeout.");
      System.out.println(
        "3 args: argHost, argPort, argTimeout, immediate connect.");
      System.out.println(
        "4 args: argHost, argPort, argTimeout, argAny - set, then connect.");

      return;
    }

    System.out.println("Start time: " + new Date());

    if (args.length == 0) {
      new EchoClientTest();
    } else {
      String theHost = args[0];
      //set up port, timeout, if sent
      if (args.length > 1) {
        try {
          thePort = Integer.parseInt(args[1]);
          if (args.length > 2) {
            theTimeout = Integer.parseInt(args[2]);
          }
        } catch(NumberFormatException nfe) {
          System.out.println(
             "Invalid port or timeout value.");
          return;
        }
      }

      if (args.length == 1) {
        new EchoClientTest(theHost);
      } else if (args.length == 2) {
        new EchoClientTest(theHost, thePort);
      } else if (args.length == 3) {
        new EchoClientTest(
          theHost, thePort, theTimeout);
      } else if (args.length == 4) {
        new EchoClientTest(
          theHost, thePort, theTimeout, true);
      }
    }
    System.out.println("End time: " + new Date());
  }
}

